#include <exception>
#include <iomanip>

#include "demuxer_rtsp.hpp"
#include "header.hpp"
#include "logger.hpp"

#define PRINT_H264_INFO 0

/**
 * @brief 构造函数
 */
demuxer_rtsp::demuxer_rtsp()
{
    fmtctx = nullptr;
    codecpar = nullptr;
    index = -1;
}

/**
 * @brief 构造函数
 * @param url RTSP 视频流地址
 * @param ringbuffer 环形缓存区对象
 */
demuxer_rtsp::demuxer_rtsp(std::string url, ringbuffer* ringbuffer, std::string ip)
{
    if (nullptr == ringbuffer) {
        Logger::error("Camera {} demuxer, The ringbuffer is nullptr!", ip);
        return;
    }

    this->url = url;
    this->rbuf = ringbuffer;
    this->ip = ip;

    fmtctx = nullptr;
    codecpar = nullptr;
    index = -1;
}

/**
 * @brief 析构函数
 */
demuxer_rtsp::~demuxer_rtsp()
{
}

/**
 * @brief 设置接口
 */
int demuxer_rtsp::set(std::string url, ringbuffer* ringbuffer, std::string ip)
{
    if (nullptr == ringbuffer) {
        Logger::error("Camera {} demuxer, The ringbuffer is nullptr!", ip);
        return -1;
    }

    this->url = url;
    this->rbuf = ringbuffer;
    this->ip = ip;

    return 0;
}

/**
 * @brief 主线程，解封装视频流，解析得到的 H264 存放在环形缓冲区中
 */
void demuxer_rtsp::thread()
{
    int cnt = 0;
    int last_widx = 0;
    bool first = true;

    int ret = init();
    if (ret) {
        Logger::error("Camera {} demuxer, Init rtsp demuxer failed!", ip);
        return;
    }

    AVPacket* packet = av_packet_alloc();
    if (!packet) {
        Logger::error("Camera {} demuxer, Could not allocate AVPacket!", ip);
        avformat_close_input(&fmtctx);
        return;
    }

    while (running) {
        if (av_read_frame(fmtctx, packet) < 0) {
            Logger::warn("Camera {} demuxer, Error reading frame! try to reinit", ip);
            std::terminate();
            continue;
        }

        /* 海康摄像头的 RTSP 视频流第一帧 pts 异常，这里手动修复下 */
        /**
         * NUM              IP       PTS     LEN IDR                        DATA
         *   1  192.168.124.21     21600  175893   1  0x00000001674d00334dc31bb8
         *   2  192.168.124.21      3600   12219   0  0x00000001219a001057cd9d10
         *   3  192.168.124.21      7200   13597   0  0x00000001219a00201e20020a
         *   4  192.168.124.21     10800   13920   0  0x00000001219a0030d2e60858
         *   5  192.168.124.21     14400   13675   0  0x00000001219a00409b001210
         *
         * 第一帧的 PTS 应该是 0，但是实际是 21600
         */
        if (first) {
            packet->pts = 0;
            packet->dts = 0;
            first = false;
        }

        if (packet->stream_index == index) {
#if PRINT_H264_INFO
            std::cout << std::setfill(' ')
                      << std::setw(16) << ip
                      << std::setw(10) << packet->pts
                      << std::setw(8) << packet->size
                      << std::setw(4) << packet->flags
                      << std::hex
                      << std::setfill('0')
                      << "  0x"
                      << std::setw(2) << static_cast<int>(packet->data[0])
                      << std::setw(2) << static_cast<int>(packet->data[1])
                      << std::setw(2) << static_cast<int>(packet->data[2])
                      << std::setw(2) << static_cast<int>(packet->data[3])
                      << std::setw(2) << static_cast<int>(packet->data[4])
                      << std::setw(2) << static_cast<int>(packet->data[5])
                      << std::setw(2) << static_cast<int>(packet->data[6])
                      << std::setw(2) << static_cast<int>(packet->data[7])
                      << std::setw(2) << static_cast<int>(packet->data[packet->size - 4])
                      << std::setw(2) << static_cast<int>(packet->data[packet->size - 3])
                      << std::setw(2) << static_cast<int>(packet->data[packet->size - 2])
                      << std::setw(2) << static_cast<int>(packet->data[packet->size - 1])
                      << std::dec
                      << " Demuxer"
                      << std::endl;
#endif

            rbuf->lock();

            /* 填充环形缓冲区 NALU 信息头 */
            header_t head;
            head.sync[0] = 'H';
            head.sync[1] = 'E';
            head.sync[2] = 'A';
            head.sync[3] = 'D';
            head.prev = last_widx;
            head.type = packet->flags;
            head.size = packet->size;
            head.pts = packet->pts;
            head.dts = packet->dts;
            last_widx = rbuf->widx_get();

            // Logger::debug("Camera {} [{}] demuxer, wrtie index = {}", ip, cnt++, last_widx);

            rbuf->write((uint8_t*)&head, sizeof(header_t));
            rbuf->write(packet->data, packet->size);
            rbuf->unlock();
        } else {
            Logger::error("Camera {} demuxer {}, Packet not video", ip, cnt);
        }

        av_packet_unref(packet);
    }

    av_packet_free(&packet);
    deinit();
}

/**
 * @brief 初始化解封装器
 */
int demuxer_rtsp::init()
{
    AVDictionary* options = nullptr;
    av_dict_set(&options, "rtsp_transport", "tcp", 0); // 使用 TCP 传输协议
    av_dict_set(&options, "stimeout", "1000000", 0); // 设置超时为1秒
    av_dict_set(&options, "max_delay", "500000", 0); // 设置最大延迟为500ms

    if (avformat_open_input(&fmtctx, url.c_str(), nullptr, &options) < 0) {
        Logger::error("Camera {} demuxer, Could not open input stream!", ip);
        return -1;
    }

    if (avformat_find_stream_info(fmtctx, nullptr) < 0) {
        Logger::error("Camera {} demuxer, Could not find stream information!", ip);
        avformat_close_input(&fmtctx);
        return -1;
    }

    for (int i = 0; i < fmtctx->nb_streams; i++) {
        if (fmtctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            index = i;
            stream = fmtctx->streams[i];
            codecpar = stream->codecpar;
            break;
        }
    }

    if (index == -1) {
        Logger::error("Camera {} demuxer, Could not find a video stream!", ip);
        avformat_close_input(&fmtctx);
        return -1;
    }

    return 0;
}

/**
 * @brief 销毁解封装器
 */
void demuxer_rtsp::deinit()
{
    avformat_close_input(&fmtctx);
}

/**
 * @brief 重新初始化解封装器
 */
int demuxer_rtsp::reinit()
{
    deinit();
    msleep(40);
    return init();
}

/**
 * @brief 启动主线程
 */
void demuxer_rtsp::start()
{
    if (!handle.joinable()) {
        running = true;
        handle = std::thread(&demuxer_rtsp::thread, this);
    }
}

/**
 * @brief 关闭主线程
 */
void demuxer_rtsp::stop()
{
    if (handle.joinable()) {
        running = false;
        handle.join();
    }
}

/**
 * @brief 毫秒延时
 */
void demuxer_rtsp::msleep(int ms)
{
    std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}
